<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, user-scalable=no">
    <title>小模块大世界</title>
    <link rel="stylesheet" type="text/css" href="https://s.momocdn.com/w/css/2017/01/10/1484040996423-CPd074ae63ddbacc4a2e8289862598ae50.css" >
    <link href="https://fonts.googleapis.com/css?family=Petit+Formal+Script" rel="stylesheet">
    <link href="http://cdnst.momocdn.com/w/u/css/2017/02/15/1487156827260-module.css" rel="stylesheet">

    <style>
      html {
        font-size: 16px;
        overflow-y:auto;
      }
      body {
        background: #051838;
      }


      .module-wrapper {
        position: absolute;
        z-index: 999;
        width: 80%;
        margin: 6rem 10%;
      }
      .module-head {
        text-align: center;
        font-size: 1.7rem;
        padding: 1rem 0;
        border-radius: 3px;
        margin-bottom: 2rem;
        background: #915991;
        color: yellow;
        box-shadow: 1px 1px 20px #fff;
      }
      .module-item {
        background: #f6e1ca;
        margin-bottom: 2.3rem;
        border-radius: 1rem;
        min-height: 20rem;
      }

      .item-title {
        font-size: 1.3rem;
        text-indent: 1rem;
        padding: 1rem 0;
      }
      .item-info {
        padding: 0 1rem;
        color: rgb(44, 36, 1);
        font-size: .7rem;
        font-family: thamo;
      }
      .item-info p {
        line-height: 1.3rem;
      }
      .note {
        color: #777;
      }
      .h3 {
        color: #d25c71;
        font-size: 1rem;
        padding: .3rem 0;
      }
      .pl1 {
        padding-left: .7rem;
      }
      .pl2 {
        padding-left: 1.4rem;
      }
      .pl3 {
        padding-left: 2.1rem;
      }
      .pl4 {
        padding-left: 2.8rem;
      }
      .pl5 {
        padding-left: 3.5rem;
      }
      .pl6 {
        padding-left: 4.2rem;
      }

    </style>
  </head>
  <body>

    <div class="bubbles" id="bubbles">
    </div>
    <div class="module-wrapper">
      <h1 class="module-head">小模块里面有大世界吗？</h1>
      <div class="module-item">
        <h3 class="item-title"> 小模块 </h3>
        <div class="item-info">
          <p class="h3">/* ===== 获取加载根路径 ===== */</p>
          <p>var loaderDir = (function(){</p>
            <p class="pl1 note">//使用正则获取一个文件所在的目录</p>
            <p class="pl1">function dirname(path) {</p>
              <p class="pl2">return path.match(/[^?#]*\//)[0]</p>
            <p class="pl1">}</p>
            <p class="pl1 note">//拿到引用seajs所在的script节点</p>
            <p class="pl1">var scripts = document.scripts</p>
            <p class="pl1">var ownScript = scripts[scripts.length - 1]</p>
            <p class="pl1 note">//获取绝对地址的兼容写法</p>
            <p class="pl1">var src = ownScript.hasAttribute ? ownScript.src : ownScript.getAttribute("src", 4)</p>
            <p class="pl1">return dirname(src)</p>
          <p>});</p>

          <p class="h3">/* ===== 异步js文件加载器 ===== */</p>
          <p>var head = document.getElementsByTagName('head')[0]</p>
          <p>var baseElement = head.getElemensByTagName('base')[0]</p>
          <p>;function request(url, callback) { </p>
            <p class="pl1"> var node = document.createElement('script')</p>
            <p class="pl1"> var supportOnload = "onload" in node</p>
            <p class="pl1"> if (supportOnload) {</p>
              <p class="pl2"> node.onload = function(){ </p>
                <p class="pl3">callback()</p>
              <p class="pl2">}</p>
            <p class="pl1"> }else {</p>
              <p class="pl2"> node.onreadystatechange = function(){</p>
                <p class="pl3"> if(/loaded|complete/.test(node.readyState)) {</p>
                  <p class="pl4"> callback()</p>
                <p class="pl3"> }</p>
              <p class="pl2"> }</p>
            <p class="pl1"> }</p>
            <p class="pl1"> node.async = true</p>
            <p class="pl1"> node.src = url</p>

            <p class="pl1"> baseElement ? head.insertBefore(node, baseElement): head.appendChild(node)</p>
          <p>}</p>

          <p class="h3">/* ===== 模块类 ===== */</p>
          <p> function Module(uri, deps) {</p>
            <p class="pl1"> this.uri = uri</p>
            <p class="pl1"> this.dependencies = deps || []</p>
            <p class="pl1"> this.factory = null</p>
            <p class="pl1"> this.status = 0</p>
            <p class="pl1 note"> //哪些模块依赖我</p>
            <p class="pl1"> this._waitings = {}</p>
            <p class="pl1 note"> 我依赖的模块还有多少没加载好</p>
            <p class="pl1"> this._remain = 0</p>
          <p>}</p>

          <p> var STATUE = Module.STATUS = {</p>
            <p class="pl1 note"> // 1 - 对应的js文件正在加载 </p>
            <p class="pl1"> FETCHING: 1,</p>
            <p class="pl1"> // 2 - js加载完毕，并且已经分析了js文件得到了一些相关信息，存储了起来</p>
            <p class="pl1"> SAVED: 2,</p>
            <p class="pl1 note"> // 3 - 依赖的模块正在加载</p>
            <p class="pl1"> LOADING: 3,</p>
            <p class="pl1 note"> // 4 - 依赖的模块也都加载好了，处于可执行状态</p>
            <p class="pl1"> LOADED: 4,</p>
            <p class="pl1 note"> // 5 - 正在执行这个模块</p>
            <p class="pl1"> EXECUTING: 5,</p>
            <p class="pl1 note"> // 6 - 这个模块执行完成</p>
            <p class="pl1"> EXECUTED: 6 </p>
          <p>}</p>

          <P class="note">// 存储实例化的模块对象</P>
          <p>cacheMods = {};</p>
          <P class="note">// 根据uri获取一个对象，没有的话就生成一个新的</P>
          <p>Module.get = function(){</p>
          <p class="pl1"> return cacheMods[uri] || (cacheMods[uri] = new Module(uri, deps))</p>
          <p>}</p>

          <p> function id2Url(id) { </p>
          <p class="pl1"> return loaderDir + id + '.js';</p>
          <p>} </p>
          <p class="note"> // 解析依赖的模块的实际地址的集合</p>
          <p class="">Module.prototype.resolve = function(){ </p>
          <p class="pl1"> var mod = this;</p>
          <p class="pl1"> var ids = mod.dependencies;</p>
          <p class="pl1"> var uris = [];</p>
          <p class="pl1"> for (var i = 0, len = ids.length; i <len; i++) {</p>
          <p class="pl2"> uris[i] = id2Url(ids[i]);</p>
          <p class="pl1">}</p>
          <p class="pl1">return uris</p>
          <p >}</p>

          <p class=""> function define(factory){</p>
          <p class="pl1 note"> //使用正则分析获取到对应的依赖模块</p>
          <p class="pl1"> deps = parseDependecies(factory.toString());
          <p class="pl1" > var meta = { </p>
          <p class="pl2"> deps: deps, </p>
          <p class="pl2"> factory: factory </p>

          <p class="pl1 note"> //存到一个全局变量，等后面fetch在script的onload回调里获取</p>
          <p class="pl1"> anonymousMeta = meta; </p>

          <p> Module.prototype.fetch = function(){ </p>
          <p class="pl1"> var mod = this; </p>
          <p class="pl1"> var uri = mod.uri; </p>
          <p class="pl1"> mod.status = STATUS.FETCHNING </p>
          <p class="pl1 note"> //调用工具函数，异步加载js</p>
          <p class="pl1"> request(uri, onRequest); </p>
          <p class="pl1 note"> //保存模块信息 </p>
          <p class="pl1">function saveModule(uri, anonyMousMeta) { </p>
          <p class="pl2 note" > //使用辅助函数获取模块，没有就实例化个新的</p>
          <p class="pl2"> var mod = Module.get(uri);</p>
          <p class="pl2 note"> //保存meta信息</p>
          <p class="pl2"> if(mod.status < STATUS.SAVED) { </p>
          <p class="pl3"> mod.id = anonymousMeta.id || uri;</p>
          <p class="pl3"> mod.dependencies = anonymousMeta.deps || [];</p>
          <p class="pl3"> mod.factory = anonymousMeta.factory; </p>
          <p class="pl3"> mod.status = STATUE.SAVED;</p>
          <p class="pl2"> } </p>
          <p class="pl1"> } </p>
          <p class="pl1"> function onRequest(){ </p>
          <p class="pl2 note"> //拿到之前define保存的meta信息</p>
          <p class="pl2"> if(anonymousMeta) { </p>
          <p class="pl3"> saveModule(uri, anonymousMeta);</p>
          <p class="pl3"> anonymousMeta = null;</p>
          <p class="pl2"> } </p>
          <p class="pl2 note"> //调用加载函数 </p>
          <p class="pl2"> mod.load();</p>
          <p class="pl1"> } </p>
          <p> } </p>

          <p> Module.prototype.load = function(){ </p>
          <p class="pl1"> var mod = this; </p>
          <p class="pl1"> if(mod.status >= STATUS.LOADING) {</p>
          <p class="pl2"> return </p>
          <p class="pl1" > } </p>
          <p class="pl1"> mod.status = STATUS.LOADING;</p>
          <p class="pl1 note"> //拿到解析后的模块依赖列表</p>
          <p class="pl1"> var uris = mod.resolve();</p>

          <p class="pl1 note"> //复制_remain </p>
          <p class="pl1"> var len = mod._remain = uris.length;</p>
          <p class="pl1"> var m; </p>
          



         



        </div>
      </div>
      <div class="module-item">
        <h3 class="item-title"> 大世界 </h3>
        <div class="item-info">

        </div>
      </div>
    </div>

    <script>
      (function(){
        var loveNumber = 23;
        var loveStr = '<div class="bubble">' +
                        '<svg class="heart" viewBox="0 0 32 32">' +
                          '<title>heart22</title>' +
                          '<path d="M23.6 2c-3.363 0-6.258 2.736-7.599 5.594-1.342-2.858-4.237-5.594-7.601-5.594-4.637 0-8.4 3.764-8.4 8.401 0 9.433 9.516 11.906 16.001 21.232 6.13-9.268 15.999-12.1 15.999-21.232 0-4.637-3.763-8.401-8.4-8.401z"></path>' +
                        '</svg>' +
                      '</div>';

        var createLoveFn  = function(){
          var res = [];
          for(var i = 0; i < loveNumber; i++) {
            res.push(loveStr);
          }

          return res.join('');
        }

        document.getElementById('bubbles').innerHTML = createLoveFn();
      })();

    </script>
  </body>
</html>
